package com.groupbuying.file.service.impl;

import com.groupbuying.file.connector.SysconfigFeign;
import com.groupbuying.file.constants.CommonConstants;
import com.groupbuying.file.domain.OssCatelogDO;
import com.groupbuying.file.domain.OssFileDO;
import com.groupbuying.file.pojo.BaseEnum;
import com.groupbuying.file.pojo.OSSServiceProvider;
import com.groupbuying.file.service.FileService;
import com.groupbuying.file.service.OssCatelogService;
import com.groupbuying.file.service.OssFileService;
import com.groupbuying.file.utils.DateFormatHelper;
import com.groupbuying.file.utils.JSONUtils;
import com.groupbuying.file.utils.R;
import com.groupbuying.file.utils.ReturnUtils;
import com.groupbuying.file.utils.apiresult.ApiResult;
import com.groupbuying.file.utils.apiresult.ApiResultCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * @anthor wenguoqiang
 * @date: 2019/02/19 12:02
 * @company 够样
 * @des
 **/
@Service
public class FileServiceImpl implements FileService {

    private static Logger log = LoggerFactory.getLogger(FileServiceImpl.class);

    @Autowired
    private OssCatelogService ossCatelogService;
    @Autowired
    private OssFileService ossFileService;
    @Autowired
    private SysconfigFeign sysconfigFeign;

    @Override
    @Transactional
    public Map<String, Object> uploadFile(Map<String, Object> mapParams) {
        Object temp = mapParams.get("files");
        MultipartFile file = temp != null ? (MultipartFile) temp : null;
        temp = mapParams.get("applicationName");
        String applicationName = temp != null ? temp.toString() : null;

        if (file == null) {
            return ReturnUtils.createReturnResult(ApiResultCode.FILENOTEXISTS.code(), ApiResultCode.FILENOTEXISTS.message(), false, "");
        }

        if (StringUtils.isBlank(applicationName)) {
            return ReturnUtils.createReturnResult(ApiResultCode.APPLICATIONISNULL.code(), ApiResultCode.APPLICATIONISNULL.message(), false, "");
        }

        try {
            //定位oss 位置
            OssCatelogDO ossCatelog = ossCatelogService.getCatelogByApplication(applicationName);
            if (ossCatelog == null) {
                return ReturnUtils.createReturnResult(ApiResultCode.OSSCATELOGISNULL.code(), ApiResultCode.OSSCATELOGISNULL.message(), true, "");
            }

            // 获取 oss 服务对象
            OSSServiceProvider ossServiceProvider = new OSSServiceProvider(ossCatelog.getAccesskeyid(), ossCatelog.getAccesskeysecret(), ossCatelog.getEndpoint(), ossCatelog.getBucketname());

            //生成 文件组code
            //String fileGroupCode = SnowflakeIdWorker.nextId("file");
            //组装数据库保存的文件数据
            List<OssFileDO> lsFile = new ArrayList<OssFileDO>();
            OssFileDO ossFileDO = null;
            String time = DateFormatHelper.getNowTimeStr();
            String originalFileName = file.getOriginalFilename();
            ossFileDO = new OssFileDO();
            //String uuid = UuidUtils.createUuid();
            ossFileDO.setUuid(sysconfigFeign.getUuidByLeaf());
            ossFileDO.setCataloguuid(ossCatelog.getUuid());
            ossFileDO.setDelflag(CommonConstants.COMMON_FLAG_UNDEL);
            ossFileDO.setFilegroupcode(sysconfigFeign.getUuidByLeaf());
            ossFileDO.setFilename(originalFileName);
            ossFileDO.setFiletype(file.getContentType());
            ossFileDO.setCreateopetime(time);
            ossFileDO.setOpetime(time);
            String[] strs = originalFileName.split("\\.");
            String postfix = "." + strs[strs.length - 1];
            //上传文件
            ossServiceProvider.putObject(ossFileDO.getUuid()+postfix, file.getInputStream());

            //释放资源
            ossServiceProvider.shutdown();

            //保存 文件数据
            ossFileService.save(ossFileDO);

            Map<String, Object> result = new HashMap<String, Object>();
            result.put("fileGorupKey", ossFileDO.getFilegroupcode());
            //return R.ok(result);
            return ApiResult.success(result);
            //return ReturnUtils.createReturnResult(ApiResultCode.OPRSUCCESS.code(), ApiResultCode.OPRSUCCESS.message(), true, result);
        } catch (Exception e){
            return R.error();
        }
    }

    @Override
    public Map<String, Object> uploadMoreFiles(Map<String, Object> mapParams) throws Exception {
        Object temp = mapParams.get("files");
        MultipartFile[] files = temp != null ? (MultipartFile[]) temp : null;
        temp = mapParams.get("applicationName");
        String applicationName = temp != null ? temp.toString() : null;

        if (files == null || files.length == 0) {
            return ReturnUtils.createReturnResult(ApiResultCode.FILENOTEXISTS.code(), ApiResultCode.FILENOTEXISTS.message(), false, "");
        }

        if (StringUtils.isBlank(applicationName)) {
            return ReturnUtils.createReturnResult(ApiResultCode.APPLICATIONISNULL.code(), ApiResultCode.APPLICATIONISNULL.message(), false, "");
        }

        try {
            //定位oss 位置
            OssCatelogDO ossCatelog = ossCatelogService.getCatelogByApplication(applicationName);
            if (ossCatelog == null) {
                return ReturnUtils.createReturnResult(ApiResultCode.OSSCATELOGISNULL.code(), ApiResultCode.OSSCATELOGISNULL.message(), true, "");
            }

            // 获取 oss 服务对象
            OSSServiceProvider ossServiceProvider = new OSSServiceProvider(ossCatelog.getAccesskeyid(), ossCatelog.getAccesskeysecret(), ossCatelog.getEndpoint(), ossCatelog.getBucketname());
            //生成 文件组cod
            String fileGroupCode = sysconfigFeign.getUuidByLeaf();

            //组装数据库保存的文件数据
            /*  List<OssFileDO> lsFile = new ArrayList<OssFileDO>();*/
            OssFileDO ossFileDO = null;
            String time = DateFormatHelper.getNowTimeStr();
            for (MultipartFile mf : files) {

                String originalFileName = mf.getOriginalFilename();

                ossFileDO = new OssFileDO();
                String uuid = sysconfigFeign.getUuidByLeaf();
                ossFileDO.setUuid(uuid);
                ossFileDO.setCataloguuid(ossCatelog.getUuid());
                ossFileDO.setDelflag(BaseEnum.DEL_FLAG_VALID);
                ossFileDO.setFilegroupcode(fileGroupCode);
                ossFileDO.setFilename(originalFileName);
                ossFileDO.setFiletype(mf.getContentType());
                ossFileDO.setCreateopetime(time);
                ossFileDO.setOpetime(time);

                String[] strs = originalFileName.split("\\.");
                String postfix = "." + strs[strs.length - 1];
                //上传文件
                ossServiceProvider.putObject(uuid+postfix, mf.getInputStream());
               // lsFile.add(ossFileDO);
                ossFileService.save(ossFileDO);
            }
            //释放资源
            ossServiceProvider.shutdown();
            // 保存 文件数据
            /*ossFileService.batchAdd(lsFile);*/

            Map<String, Object> result = new HashMap<String, Object>();
            result.put("fileGroupKey", fileGroupCode);

            return ApiResult.success(result);
        } catch (IOException e) {
            e.printStackTrace();
           return R.error();
        }
    }

    @Override
    public Map<String, Object> tempVisit(Map<String, Object> mapParams) {
        Object temp = mapParams.get("expires");
        Long expires = temp != null ? (Long) temp : null;
        temp = mapParams.get("fileGorupKey");
        String fileGorupKey = temp != null ? temp.toString() : null;
        if (expires == null && StringUtils.isBlank(fileGorupKey)) {
            return ReturnUtils.paramIsNull();
        }
        List<OssFileDO> lsFile = ossFileService.queryByFileGroupCode(fileGorupKey);
        if (lsFile == null && !(lsFile.size() > 0)) {
            return ReturnUtils.createReturnResult(ApiResultCode.FILENOTEXISTS.code(), ApiResultCode.FILENOTEXISTS.message(), false, "");
        }
        // 获取 oss 定位
        OssCatelogDO ossCatelog = ossCatelogService.get(lsFile.get(0).getCataloguuid());
        if (ossCatelog == null) {
            return ReturnUtils.createReturnResult(ApiResultCode.OSSCATELOGISNULL.code(), ApiResultCode.OSSCATELOGISNULL.message(), true, "");
        }
        //生成oss 提供者
        OSSServiceProvider ossServiceProvider = new OSSServiceProvider(ossCatelog.getAccesskeyid(), ossCatelog.getAccesskeysecret(), ossCatelog.getEndpoint(), ossCatelog.getBucketname());

        Date expiration = new Date(new Date().getTime() + expires);
        List<String> list = new ArrayList<>();
        for (OssFileDO ossFile : lsFile) {
            URL url = ossServiceProvider.generatePresignedUrl(ossFile.getUuid(), expiration);
            list.add(url.toString());
        }

        return ReturnUtils.createReturnResult(ApiResultCode.OPRSUCCESS.code(), ApiResultCode.OPRSUCCESS.message(), true, JSONUtils.beanToJson(list));
    }

    @Override
    public Map<String, Object> singleDownLoadFile(Map<String, Object> mapParams) {

        Object temp = mapParams.get("fileUuid");
        String fileUuid = temp != null ? temp.toString() : null;
        if (StringUtils.isBlank(fileUuid)) {
            return ReturnUtils.paramIsNull();
        }
        // 获取文件
        OssFileDO ossFile = ossFileService.get(fileUuid);
        if (ossFile == null) {
            return ReturnUtils.createReturnResult(ApiResultCode.FILENOTEXISTS.code(), ApiResultCode.FILENOTEXISTS.message(), false, "");
        }
        // 获取 oss 定位
        OssCatelogDO ossCatelog = ossCatelogService.get(ossFile.getCataloguuid());
        if (ossCatelog == null) {
            return ReturnUtils.createReturnResult(ApiResultCode.OSSCATELOGISNULL.code(), ApiResultCode.OSSCATELOGISNULL.message(), true, "");
        }
        //生成oss 提供者
        OSSServiceProvider ossServiceProvider = new OSSServiceProvider(ossCatelog.getAccesskeyid(), ossCatelog.getAccesskeysecret(), ossCatelog.getEndpoint(), ossCatelog.getBucketname());

        InputStream in = ossServiceProvider.getOSSObjectStream(ossFile.getUuid());

        Map result = new HashMap();
        result.put("fileName", ossFile.getFilename());
        result.put("fileType", ossFile.getFiletype());
        result.put("stream", in);

        return result;
    }

    /**
     * feign 方式下载有内存溢出风险 必须使用 ResponseEntity<Resource> 方式返回
     * @param fileUuid
     * @return
     */
    @Override
    public ResponseEntity<Resource> getFileStream(String fileUuid) throws Exception {

        if (StringUtils.isBlank(fileUuid)) {
            log.error("fileUuid 不存在");
            throw new Exception("\"fileUuid 不存在\"");
        }
        // 获取文件
        OssFileDO ossFile = ossFileService.get(fileUuid);
        if (ossFile == null) {
            log.error("数据库中文件数据不存在");
            throw new Exception("\"数据库中文件数据不存在\"");
        }
        // 获取 oss 定位
        OssCatelogDO ossCatelog = ossCatelogService.get(ossFile.getCataloguuid());
        if (ossCatelog == null) {
            log.error("数据库中文件数据定位不存在");
            throw new Exception("\"数据库中文件数据定位不存在\"");
        }

        //生成oss 提供者
        OSSServiceProvider ossServiceProvider = new OSSServiceProvider(ossCatelog.getAccesskeyid(), ossCatelog.getAccesskeysecret(), ossCatelog.getEndpoint(), ossCatelog.getBucketname());
        InputStream in = null;
        try {
            in = ossServiceProvider.getOSSObjectStream(ossFile.getUuid());
            InputStreamResource resource = new InputStreamResource(in);

            //头信息
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition","inline;filename="+ ossFile.getFilename());

            return ResponseEntity
                    .ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .headers(null)
                    .body(resource);

        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public List<String> getFileUuids(String fileGroupKey) throws Exception {
        if (StringUtils.isBlank(fileGroupKey)) {
            log.error("fileUuid 不存在");
            throw new Exception("\"fileUuid 不存在\"");
        }
        // 获取文件
        List<OssFileDO> lsFile = ossFileService.queryByFileGroupCode(fileGroupKey);
        if (lsFile == null && !(lsFile.size() > 0)) {
            log.error("数据库中文件数据不存在");
            throw new Exception("\"数据库中文件数据不存在\"");
        }
        int len = lsFile.size();
        List<String> fileUuids = new ArrayList<String>(len);
        for (int i = 0; i < len; i++) {
            fileUuids.add( lsFile.get(i).getUuid());
        }
        return fileUuids;

    }

    @Override
    public List<String> getOssFileNames(String fileGroupKey)throws Exception {
        if (StringUtils.isBlank(fileGroupKey)) {
            log.error("ossFileName 不存在");
            throw new Exception("\"o`ssFileName 不存在\"");
        }
        // 获取文件
        List<OssFileDO> lsFile = ossFileService.queryByFileGroupCode(fileGroupKey);
        if (lsFile == null && !(lsFile.size() > 0)) {
            log.error("数据库中文件数据不存在");
            throw new Exception("\"数据库中文件数据不存在\"");
        }
        int len = lsFile.size();
        List<String> ossFileNames = new ArrayList<String>(len);
        for (int i = 0; i < len; i++) {
            OssFileDO ossFile = lsFile.get(i);
            String[] strs = ossFile.getFilename().split("\\.");
            ossFileNames.add(ossFile.getUuid() + "." + strs[strs.length - 1]);
        }
        return ossFileNames;
    }

    @Override
    public Map<String, Object> singleDownLoadFileByOssFileName(Map mapParam) {

        Object temp = mapParam.get("ossFileName");
        String ossFileName = temp != null ? temp.toString() : null;
        if (StringUtils.isBlank(ossFileName)) {
            return ReturnUtils.paramIsNull();
        }
        // 获取文件
        OssFileDO ossFile = ossFileService.get(ossFileName.split("\\.")[0]);
        if (ossFile == null) {
            return ReturnUtils.createReturnResult(ApiResultCode.FILENOTEXISTS.code(), ApiResultCode.FILENOTEXISTS.message(), false, "");
        }
        // 获取 oss 定位
        OssCatelogDO ossCatelog = ossCatelogService.get(ossFile.getCataloguuid());
        if (ossCatelog == null) {
            return ReturnUtils.createReturnResult(ApiResultCode.OSSCATELOGISNULL.code(), ApiResultCode.OSSCATELOGISNULL.message(), true, "");
        }
        //生成oss 提供者
        OSSServiceProvider ossServiceProvider = new OSSServiceProvider(ossCatelog.getAccesskeyid(), ossCatelog.getAccesskeysecret(), ossCatelog.getEndpoint(), ossCatelog.getBucketname());

        InputStream in = ossServiceProvider.getOSSObjectStream(ossFileName);

        Map result = new HashMap();
        result.put("fileName", ossFile.getFilename());
        result.put("fileType", ossFile.getFiletype());
        result.put("stream", in);

        return result;
    }

    @Override
    public String getOssFileNameByFileUuid(String fileUuid) throws Exception {
        if (StringUtils.isBlank(fileUuid)) {
            log.error("fileUuid 不存在");
            throw new Exception("\"fileUuid 不存在\"");
        }
        OssFileDO ossFile = ossFileService.get(fileUuid);
        String[] strs = ossFile.getFilename().split("\\.");
        String postfix = "." + strs[strs.length - 1];
        return fileUuid + postfix;
    }

    @Override
    public String getDownLoadUrl(String fileUuid) throws Exception {
        if (StringUtils.isBlank(fileUuid)) {
            log.error("fileUuid 不存在");
            throw new Exception("\"fileUuid 不存在\"");
        }
        OssFileDO ossFile = ossFileService.get(fileUuid);

        if (ossFile == null) {
            log.error("ossFile 不存在");
            throw new Exception("\"ossFile 不存在\"");
        }
        // 获取 oss 定位
        OssCatelogDO ossCatelog = ossCatelogService.get(ossFile.getCataloguuid());
        if (ossCatelog == null) {
            log.error("ossCatelog 不存在");
            throw new Exception("\"ossCatelog 不存在\"");
        }
        String[] strs = ossFile.getFilename().split("\\.");
        String ossFileName = ossFile.getUuid() + "." + strs[strs.length - 1];
        StringBuffer buffer = new StringBuffer();
        buffer.append("http://");
        buffer.append(ossCatelog.getBucketDomainName());
        buffer.append("/");
        buffer.append(ossFileName);
        return buffer.toString();
    }

    @Override
    public List<String> getDownloadUrlByFileGroupKey(String fileGroupKey)throws Exception {

        if (StringUtils.isBlank(fileGroupKey)) {
            log.error("fileGroupKey 不存在");
            throw new Exception("\"fileGroupKey 不存在\"");
        }
        List<OssFileDO> ossFiles = ossFileService.queryByFileGroupCode(fileGroupKey);

        if (ossFiles == null || !(ossFiles.size()>0)) {
            log.error("ossFile 不存在");
            throw new Exception("\"ossFile 不存在\"");
        }
        // 获取 oss 定位
        OssCatelogDO ossCatelog = ossCatelogService.get(ossFiles.get(0).getCataloguuid());
        if (ossCatelog == null) {
            log.error("ossCatelog 不存在");
            throw new Exception("\"ossCatelog 不存在\"");
        }
        List<String> list = new ArrayList<>();
        StringBuffer buffer = null;
        for(OssFileDO ossFile : ossFiles){
            String[] strs = ossFile.getFilename().split("\\.");
            String ossFileName = ossFile.getUuid() + "." + strs[strs.length - 1];
            buffer = new StringBuffer();
            buffer.append("http://");
            buffer.append(ossCatelog.getBucketDomainName());
            buffer.append("/");
            buffer.append(ossFileName);
            list.add(buffer.toString());
        }

        return list;
    }


}
